package it.softphone.cmc.server.rest;

import it.softphone.cmc.server.service.TaskQueueService;
import it.softphone.cmc.server.service.exception.CMCException;
import it.softphone.cmc.shared.entity.Account;
import it.softphone.commons.json.server.JSONUtils;
import it.softphone.commons.json.server.jersey.JSONExceptionMapper;
import it.softphone.commons.spring.ApplicationConfig;

import java.security.GeneralSecurityException;

import javax.security.auth.login.AccountLockedException;
import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.CredentialNotFoundException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;


import com.sun.jersey.core.util.MultivaluedMapImpl;

/**
 * 
 * @author bsorrentino
 *
 */
@Path("auth")
public class CMCAuthManager extends RESTServiceAware  {
	
	
	/**
	 * user in login.jsp
	 * 
	 * @return
	 */
	public static String loggedUserAsJson() {
		try {

			Account account = security().getPrincipal(Account.class);

			if( account != null ) {

				it.softphone.commons.json.server.JSONObject o =  new it.softphone.commons.json.server.JSONObject(account);
				
				return o.toString();
			}
			
			
		} catch (Throwable e) {
			logger.error( "loggedUserAsJson",e );
		}

		return "";
		
	}
	
	/**
	 * 
	 * @return
	 */
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public it.softphone.commons.json.server.JSONObject getLoggedAccount() {
		
		Account account = security().getPrincipal(Account.class);

		if( account == null ) {
			throw new JSONExceptionMapper( Response.status(Status.NOT_FOUND).entity("account not found!").build() );
		}
		
		return new it.softphone.commons.json.server.JSONObject(account);
			
	}
	
	/**
	 * 
	 * @return
	 * @throws GeneralSecurityException 
	 * @throws AccountLockedException 
	 * @throws CredentialNotFoundException 
	 * @throws AccountNotFoundException 
	 */
	@POST
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	@Produces(MediaType.APPLICATION_JSON)
	public it.softphone.commons.json.server.JSONObject loginAccount(	
										@FormParam("username") String login,  
										@FormParam("password") String password, 
										@FormParam("rememberMe") @DefaultValue("false") boolean rememberMe
										) throws 	AccountNotFoundException, 
													CredentialNotFoundException, 
													AccountLockedException, 
													GeneralSecurityException 
	{
		
		security().login(login, password, rememberMe);
		
		Account account = security().getPrincipal(Account.class);
		
		return new it.softphone.commons.json.server.JSONObject(account);
			
	}

	/**
	 * 
	 * @return
	 */
	@DELETE
	@Produces(MediaType.TEXT_PLAIN)
	public Response logoutAccount() {


    	try {

    		security().logout();
    		
			return Response.ok("OK").build();
		
		} catch (Exception e) {
			
			return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(JSONUtils.toJSON(e)).build();
			
		}
	}

	/**
	 * 
	 * @param email
	 * @param password
	 * @param ui
	 * @return
	 */
	@GET
	@Path("register/1")
	public Response requestAccountCreation( @QueryParam("email") String email, 
											@QueryParam("password") String password, 
											@QueryParam("deviceid") @DefaultValue("") String deviceId, 
											@Context UriInfo ui )  
	{

		java.net.URI baseUri =  ui.getBaseUri();
		java.net.URI requestUri = ui.getRequestUri();
		
		logger.debug( String.format("==> baseUri [%s]\n ==> requestUri [%s] ", baseUri, requestUri ));
		
		try {
			/*String requestToken = */system().requestAccountCreation(email, password, deviceId, ui.getBaseUri().toString());
		
		} catch (CMCException e) {
			throw new javax.ws.rs.WebApplicationException( Response.serverError().entity("error requesting registration").build() );
			
		}
		return Response.ok().build();
	}
	
	/**
	 * 
	 * @param requestToken
	 * @return
	 */
	@GET
	@Path("register/2")
	@Produces(MediaType.TEXT_PLAIN)
	public Response confirmAccountCreation( @QueryParam("requestToken") String requestToken )  {

		try {
			/*Account account = */system().confirmAccountCreation(requestToken);
					
		} catch (CMCException e) {
			throw new javax.ws.rs.WebApplicationException( Response.serverError().entity("error on account confirmation").build() );
			
		}
		return Response.ok( "Account registered!").build();
	}

	
	/**
	 * 
	 * @param email
	 * @param password
	 * @param ui
	 * @return
	 */
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	@Path("register")
	public Response requestAccountCreationAsync( 
											@QueryParam("email") String email, 
											@QueryParam("password") String password, 
											@QueryParam("deviceid") @DefaultValue("") String deviceId, 
											@QueryParam(REDIRECT_URI_PARAM) @DefaultValue(NO_REDIRECT) String redirect_uri,
											@Context UriInfo ui,
											@Context HttpHeaders hh	
											)  
	{

		TaskQueueService service = ApplicationConfig.getBean(TaskQueueService.class);
	
    	final String taskUri = new StringBuilder()
    								.append( ui.getBaseUri().getPath() )
    								.append( "auth/register/1")
    								.toString();

    	logger.debug( String.format("requestAccountCreationAsync taskUri[%s]", taskUri ));
    	
    	MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    	
    	params.add("email", email);
    	params.add("password", password);
    	params.add("deviceid", deviceId);
    	params.add("REDIRECT_URI_PARAM", redirect_uri);
    	
    	service.schedule( TaskQueueService.Method.GET, taskUri, params, hh );
    	
		return Response.ok("task scheduled").build();

    }
	
}
